package xyz.scootaloo.draft.io;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * 向文件写入字符
 * @author flutterdash@qq.com
 * @since 2021/5/16 11:41
 */
public class WriteToFile {

    public static void main(String[] args) {
        new Shell().start();
    }

    public static void print(String s) {
        System.out.print(s);
    }

    public static void println(String s) {
        System.out.println(s);
    }

    private static class Shell {
        private static final String PROMPT = "console> ";
        private static final String EXIT_COMMAND = "exit";
        private static final OptionFactory OPTIONS = new OptionFactory();
        private static final Scanner scanner = new Scanner(System.in);

        /**
         * 循环读取控制台输入, 并且对输入进行处理
         */
        public void start() {
            while (true) {
                String command = readInput();
                boolean sign = handle(command);
                if (sign)
                    break;
            }
            println("");
        }

        private String readInput() {
            print(PROMPT);
            return scanner.nextLine();
        }

        private boolean handle(String command) {
            if (command.equals(EXIT_COMMAND))
                return true;
            OPTIONS.doHandle(command);
            return false;
        }

    }

    private static class OptionFactory {
        private final Map<String, Handler> optionMap = new HashMap<>();
        private final Context context = new Context();
        private Exception lastException;
        public OptionFactory() {
            optionMap.put("open", this::openFile);
            optionMap.put("cat", this::cat);
            optionMap.put("show exception", this::showException);
            optionMap.put("help", this::help);
            optionMap.put("append", this::append);
        }

        public void doHandle(String command) {
            try {
                if (command.trim().equals(""))
                    return;
                for (Map.Entry<String, Handler> optionEntry: optionMap.entrySet()) {
                    if (command.startsWith(optionEntry.getKey())) {
                        optionEntry.getValue().handle(getContent(command));
                        return;
                    }
                }
                println("没有这个命令");
            } catch (Exception ex) {
                lastException = ex;
                println("执行命令 `" + command + "` 时出错, 输入 show exception 查看异常调用栈");
            }
        }

        public void help(String command) {
            optionMap.forEach((key, value) -> println(key));
        }

        public String getContent(String command) {
            int spaceIndex = command.indexOf(' ');
            if (spaceIndex == -1)
                return command;
            return command.substring(spaceIndex).trim();
        }

        private void openFile(String filename) {
            File file = new File(realFilename(filename));
            if (!file.exists()) {
                println("文件不存在, 无法打开");
                return;
            }

            context.currentFile = file;
        }

        private void cat(String cat) throws IOException {
            if (hasSelected()) return;
            try (BufferedReader bufferedReader =
                         new BufferedReader(
                                 new FileReader(context.currentFile))) {
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    println(line);
                }
            }
        }

        private void append(String options) throws IOException {
            if (hasSelected()) return;
            try (BufferedWriter bufferedWriter =
                         new BufferedWriter(
                                 new FileWriter(context.currentFile, true))) { // 追加模式
                String line = Shell.scanner.nextLine();
                while (!line.equals("..")) {
                    bufferedWriter.write(line + "\n");
                    bufferedWriter.flush();
                    line = Shell.scanner.nextLine();
                }
            }
        }

        private boolean hasSelected() {
            if (context.currentFile == null) {
                println("当前没有打开的文件");
                return true;
            } else {
                return false;
            }
        }

        private void showException(String ignore) {
            if (lastException == null)
                println("暂时没有异常");
            else {
                synchronized (System.err) {
                    lastException.printStackTrace();
                }
            }
        }

        private String realFilename(String filename) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i<filename.length(); i++) {
                char c = filename.charAt(i);
                if (c == '\\') {
                    sb.append('\\').append('\\');
                } else {
                    sb.append(c);
                }
            }
            return sb.toString();
        }

    }

    @FunctionalInterface
    private interface Handler {
        void handle(String text) throws Exception;
    }

    private static class Context {
        File currentFile;
    }

}
